﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.Remoting.Contexts;
using System.Text;
using System.Web;
using ABC.Core.Configuration;
using ABC.Domain.Entities;
using ABC.Domain.Serialization;
using iTextSharp.text;
using iTextSharp.text.pdf;
using Font = iTextSharp.text.Font;
using Rectangle = iTextSharp.text.Rectangle;

namespace ABC.Business.Models
{
    public class Row
    {
        public string Key1 { get; set; }
        public string Value1 { get; set; }
        public string Key2 { get; set; }
        public string Value2 { get; set; }
    }
    public class PdfModel
    {
        private readonly RosModel rosModel;
        private readonly RbsCalcModel rbsCalcModel;

        private BaseFont Base1Font { get; set; }
        private BaseFont Base2Font { get; set; }
        private BaseFont Base3Font { get; set; }
        private BaseFont Base4Font { get; set; }

        private Font Calibri { get; set; }
        private Font CalibriZ { get; set; }
        private Font CalibriBd { get; set; }
        private Font Calibrii { get; set; }

        private BaseColor ColorBackgroundDefault { get; set; }
        private BaseColor ColorBorderDefault { get; set; }

        private float SpacingAfter { get; set; }

        public PdfModel(RosModel rosModel, RbsCalcModel rbsCalcModel)
        {
            this.rosModel = rosModel;
            this.rbsCalcModel = rbsCalcModel;
            Base1Font = BaseFont.CreateFont(HttpContext.Current.Server.MapPath("~/fonts/calibri.ttf"), BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
            Base2Font = BaseFont.CreateFont(HttpContext.Current.Server.MapPath("~/fonts/calibriz.ttf"), BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
            Base3Font = BaseFont.CreateFont(HttpContext.Current.Server.MapPath("~/fonts/calibrib.ttf"), BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
            Base4Font = BaseFont.CreateFont(HttpContext.Current.Server.MapPath("~/fonts/calibrii.ttf"), BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
            Calibri = new Font(Base1Font, 12);
            CalibriZ = new Font(Base2Font, 12);
            CalibriBd = new Font(Base3Font, 12);
            Calibrii = new Font(Base4Font, 12);
            ColorBackgroundDefault = new BaseColor(226, 226, 226);
            ColorBorderDefault = new BaseColor(Color.DimGray);
            SpacingAfter = 15f;
        }

        public void GetPdfDocument(string id, Document document, PdfWriter writer)
        {
            var kasko = rbsCalcModel.GetCalculationKasko(id);
            kasko.DateOfCalculation = rosModel.GetEntityValue<DateTime>(id, "ДатаСозданияОбъекта").ToString("от dd MMMM, HH:mm");
            document.Open();
            document.Add(new Phrase(string.Format("Расчет № {0} {1}", kasko.UniqueNumber, kasko.DateOfCalculation), new Font(Base3Font, 14, 0, BaseColor.GRAY)));
            var table1 = new List<Row>();
            table1.Add(new Row { Key1 = "Регион", Value1 = kasko.Region, Key2 = "Категория ТС", Value2 = kasko.CategoryTs });
            table1.Add(new Row { Key1 = "Собственник ТС", Value1 = kasko.OwnerTs, Key2 = "Риск", Value2 = kasko.Risk });
            table1.Add(new Row { Key1 = "Страхователь", Value1 = kasko.Insurant, Key2 = "Лимит ответственности", Value2 = kasko.Limit });
            document.Add(DrawTable(table1, "Регион"));
            var table2 = new List<Row>();
            table2.Add(new Row { Key1 = "Марка", Value1 = kasko.CarManufacture, Key2 = "Гарантия", Value2 = kasko.Guaranty });
            table2.Add(new Row { Key1 = "Модель", Value1 = kasko.CarModel, Key2 = "Пробег", Value2 = kasko.Path + kasko.UnitPath });
            table2.Add(new Row { Key1 = "Год выпуска", Value1 = kasko.Release, Key2 = "Объем двигателя", Value2 = kasko.Engine });
            table2.Add(new Row { Key1 = "ТС из салона", Value1 = kasko.IsNewCar, Key2 = "Мощность", Value2 = kasko.Power });
            table2.Add(new Row { Key1 = "Начало эксплуатации", Value1 = kasko.BeginningOfOperation, Key2 = "Кредит", Value2 = kasko.Credit });
            table2.Add(new Row { Key1 = "Дата выдачи ПТС", Value1 = kasko.Pts, Key2 = "Стоимость ТС", Value2 = !string.IsNullOrEmpty(kasko.Cost) ? kasko.Cost + " " + kasko.Currency : "" });
            document.Add(DrawTable(table2, "Сведения о ТС"));
            var table3 = new List<Row>();
            table3.Add(new Row { Key1 = "Франшиза", Value1 = string.Format("{0} {1}", !string.IsNullOrEmpty(kasko.FranshizaInRub) ? kasko.FranshizaInRub + " руб." : "", !string.IsNullOrEmpty(kasko.FranshizaInProc) ? kasko.FranshizaInProc + " %" : ""), Key2 = "Предельный пробег", Value2 = kasko.Maxpath + kasko.UnitMaxPath });
            table3.Add(new Row { Key1 = "Форма возмещения", Value1 = kasko.Compensation, Key2 = "Количество ТС", Value2 = kasko.QuantityTs });
            table3.Add(new Row { Key1 = "Оплата", Value1 = kasko.Payment, Key2 = "Руль", Value2 = kasko.ControlWheel });
            table3.Add(new Row { Key1 = "Срок страхования", Value1 = kasko.InsurancePeriod, Key2 = "Количество мест", Value2 = kasko.Landing });
            table3.Add(new Row { Key1 = "Переход из другой СК", Value1 = kasko.Transition, Key2 = "Максимальная масса", Value2 = kasko.MaxMass });
            table3.Add(new Row { Key1 = "Условия хранения", Value1 = kasko.StorageCondition, Key2 = "Грузоподъемность", Value2 = kasko.Mass });
            document.Add(DrawTable(table3, "Дополнительные условия"));

            document.Add(kasko.TypeDrivers == "Ограниченное количество"
                             ? DrawTableDriversLimited(kasko.Drivers)
                             : DrawTableDriversUnlimited(kasko.MinAge, kasko.MinPeriod));

            var table4 = new List<Row>();
            table4.Add(new Row { Key1 = "ЭПС", Value1 = kasko.Signaling, Key2 = "МПУ", Value2 = kasko.Mpu });
            table4.Add(new Row { Key1 = "Дополнительная ЭПС", Value1 = kasko.SignalingAdd, Key2 = "Иммобилайзер", Value2 = kasko.Immo });
            table4.Add(new Row { Key1 = "Автозапуск", Value1 = kasko.Autostart, Key2 = "Противоугонный комплекс", Value2 = kasko.Siganticreep });
            table4.Add(new Row { Key1 = "Метка", Value1 = kasko.Siglabel, Key2 = "Защита от глушения", Value2 = kasko.Sigantidamping });
            document.Add(DrawTable(table4, "Системы безопасности"));
            AddFooter(document);
            
            writer.PageEvent = new Footer();
            document.Add(new Phrase(string.Format("Расчет № {0} {1}", kasko.UniqueNumber, kasko.DateOfCalculation), new Font(Base3Font, 14, 0, BaseColor.GRAY)));
            document.Add(DrawTableResults(kasko.KaskoResults, document, kasko.FranshizaInRub, kasko.FranshizaInProc));
        }

        public void AddFooter(Document document)
        {
            var div3 = new PdfDiv();
            div3.Position = PdfDiv.PositionType.ABSOLUTE;
            div3.PaddingTop = 800f;
            div3.AddElement(new Phrase("Расчет сделан с помощью сервиса «Азбука24»", new Font(Base3Font, 14, 0, BaseColor.GRAY)));
            document.Add(div3);
            var div4 = new PdfDiv();
            div4.Position = PdfDiv.PositionType.ABSOLUTE;
            div4.PaddingLeft = 300f;
            var anchor1 = new Chunk("http://www.azb24.ru", new Font(Base3Font, 14, 0, BaseColor.BLUE));
            anchor1.SetAnchor("http://www.azb24.ru");
            div4.AddElement(anchor1);
            document.Add(div4);
        }

        private PdfPTable DrawTableResults(List<KaskoResult> results, Document document, string franshizaInRub, string franshizaInProc)
        {
            var countColumns = franshizaInProc == "0" && franshizaInRub == "0" ? 5 : 6;
            var isFr = countColumns != 5;
            var table = new PdfPTable(countColumns);
            if (isFr)
            {
                table.SetWidths(new[] { 4, 3, 3, 3, 10, 10 });
            }
            else
            {
                table.SetWidths(new[] { 4, 3, 3, 10, 10 });
            }
            table.WidthPercentage = 100f;
            table.DefaultCell.PaddingBottom = 4;
            table.DefaultCell.PaddingTop = 4;
            table.DefaultCell.BorderColor = ColorBorderDefault;

            var headerFont = new Font(Base3Font, 12, 0, ColorBorderDefault);
            var cellHeader = new PdfPCell(new Phrase("Страховая компания", headerFont));
            cellHeader.BackgroundColor = ColorBackgroundDefault;
            cellHeader.HorizontalAlignment = Element.ALIGN_LEFT;
            cellHeader.PaddingBottom = 4;
            cellHeader.PaddingTop = 4;
            cellHeader.BorderColor = ColorBorderDefault;
            table.AddCell(cellHeader);

            cellHeader.Phrase = new Phrase("Тариф", headerFont);
            table.AddCell(cellHeader);
            cellHeader.Phrase = new Phrase("Премия", headerFont);
            table.AddCell(cellHeader);
            if (isFr)
            {
                cellHeader.Phrase = new Phrase("Франшиза", headerFont);
                table.AddCell(cellHeader);
            }
            cellHeader.Phrase = new Phrase("Сервисные программы", headerFont);
            table.AddCell(cellHeader);
            cellHeader.Phrase = new Phrase("Прочие условия", headerFont);
            table.AddCell(cellHeader);

            var cellGray = new PdfPCell();
            cellGray.BackgroundColor = ColorBackgroundDefault;
            cellGray.HorizontalAlignment = Element.ALIGN_LEFT;
            cellGray.PaddingBottom = 4;
            cellGray.PaddingTop = 4;
            cellGray.BorderColor = ColorBorderDefault;

            for (var i = 0; i < results.Count; i++)
            {
                if (i % 2 == 0)
                {
                    table.AddCell(new Phrase(results[i].CompanyName, Calibri));
                    table.AddCell(new Phrase(results[i].KaskoRate.ToString("N2"), Calibri));
                    table.AddCell(new Phrase(results[i].KaskoValue.ToString("N2"), Calibri));
                    if (isFr)
                    {
                        table.AddCell(new Phrase(string.Format("{0} руб. {1}%", franshizaInRub, franshizaInProc), Calibri));
                    }
                    table.AddCell(new Phrase(results[i].ServiceProgram, Calibri));
                    table.AddCell(new Phrase(results[i].AdditionalConditions, Calibri));
                }
                else
                {
                    cellGray.Phrase = new Phrase(results[i].CompanyName, Calibri);
                    table.AddCell(cellGray);
                    cellGray.Phrase = new Phrase(results[i].KaskoRate.ToString("N2"), Calibri);
                    table.AddCell(cellGray);
                    cellGray.Phrase = new Phrase(results[i].KaskoValue.ToString("N2"), Calibri);
                    table.AddCell(cellGray);
                    if (isFr)
                    {
                        cellGray.Phrase = new Phrase(string.Format("{0} руб. {1}%", franshizaInRub, franshizaInProc), Calibri);
                        table.AddCell(cellGray);
                    }
                    cellGray.Phrase = new Phrase(results[i].ServiceProgram, Calibri);
                    table.AddCell(cellGray);
                    cellGray.Phrase = new Phrase(results[i].AdditionalConditions, Calibri);
                    table.AddCell(cellGray);
                }
            }
            return table;
        }


        public PdfPTable DrawTableDriversUnlimited(string minAge, string minPeriod)
        {
            var table = new PdfPTable(4);
            table.WidthPercentage = 100f;
            table.DefaultCell.PaddingBottom = 4;
            table.DefaultCell.PaddingTop = 4;
            table.DefaultCell.BorderColor = ColorBorderDefault;

            var cellHeader =
                new PdfPCell(new Phrase("Сведения о водителях", new Font(Base3Font, 12, 0, ColorBorderDefault)))
                    {
                        BackgroundColor = ColorBackgroundDefault,
                        HorizontalAlignment = Element.ALIGN_LEFT,
                        Colspan = 4,
                        PaddingBottom = 4,
                        PaddingTop = 4,
                        BorderColor = ColorBorderDefault
                    };
            table.AddCell(cellHeader);

            var cellGray = new PdfPCell
                               {
                                   BackgroundColor = ColorBackgroundDefault,
                                   HorizontalAlignment = Element.ALIGN_LEFT,
                                   PaddingBottom = 4,
                                   PaddingTop = 4,
                                   BorderColor = ColorBorderDefault,
                                   Phrase = new Phrase("Количество водителей", CalibriBd)
                               };

            table.AddCell(cellGray);
            cellGray.Phrase = new Phrase("Неограниченное количество", Calibri);
            table.AddCell(cellGray);
            cellGray.Colspan = 2;
            cellGray.Phrase = new Phrase(" ");
            table.AddCell(cellGray);

            table.AddCell(new Phrase("Минимальный возраст", CalibriBd));
            table.AddCell(new Phrase(minAge, Calibri));
            table.AddCell(new Phrase("Минимальный стаж", CalibriBd));
            table.AddCell(new Phrase(minPeriod, Calibri));
            table.SpacingAfter = SpacingAfter;

            return table;
        }

        public PdfPTable DrawTableDriversLimited(List<Driver> drivers)
        {
            var table = new PdfPTable(8) {WidthPercentage = 100f};
            table.DefaultCell.PaddingBottom = 4;
            table.DefaultCell.PaddingTop = 4;
            table.DefaultCell.BorderColor = ColorBorderDefault;
            table.SetWidths(new[] { 25, 25, 5, 16, 10, 7, 7, 7 });

            var cellHeader =
                new PdfPCell(new Phrase("Сведения о водителях", new Font(Base3Font, 12, 0, ColorBorderDefault)))
                    {
                        BackgroundColor = ColorBackgroundDefault,
                        HorizontalAlignment = Element.ALIGN_LEFT,
                        Colspan = 8,
                        PaddingBottom = 4,
                        PaddingTop = 4,
                        BorderColor = ColorBorderDefault
                    };
            table.AddCell(cellHeader);

            var cellCountDrivers = new PdfPCell(new Phrase("Количество водителей", CalibriBd));
            cellCountDrivers.BorderColor = ColorBorderDefault;
            cellCountDrivers.Rowspan = drivers.Count + 1;
            table.AddCell(cellCountDrivers);

            cellCountDrivers.Phrase = new Phrase(string.Format("Ограниченное количество: {0}", GetDriver(drivers.Count)), Calibri);
            table.AddCell(cellCountDrivers);

            var cellGray = new PdfPCell
                               {
                                   BackgroundColor = ColorBackgroundDefault,
                                   HorizontalAlignment = Element.ALIGN_LEFT,
                                   PaddingBottom = 4,
                                   PaddingTop = 4,
                                   BorderColor = ColorBorderDefault,
                                   Phrase = new Phrase("#", CalibriBd)
                               };

            table.AddCell(cellGray);
            cellGray.Phrase = new Phrase("Пол", CalibriBd);
            table.AddCell(cellGray);
            cellGray.Phrase = new Phrase("Возраст", CalibriBd);
            table.AddCell(cellGray);
            cellGray.Phrase = new Phrase("Стаж", CalibriBd);
            table.AddCell(cellGray);
            cellGray.Phrase = new Phrase("Брак", CalibriBd);
            table.AddCell(cellGray);
            cellGray.Phrase = new Phrase("Дети", CalibriBd);
            table.AddCell(cellGray);

            for (var i = 0; i < drivers.Count; i++)
            {
                if (i % 2 == 0)
                {
                    table.AddCell(new Phrase((i + 1).ToString(), Calibri));
                    table.AddCell(new Phrase(drivers[i].Sex == "М" ? "Мужчина" : "Женщина", Calibri));
                    table.AddCell(new Phrase(drivers[i].Age, Calibri));
                    table.AddCell(new Phrase(drivers[i].Experience, Calibri));
                    table.AddCell(new Phrase(drivers[i].Married, Calibri));
                    table.AddCell(new Phrase(drivers[i].Children, Calibri));
                }
                else
                {
                    cellGray.Phrase = new Phrase((i + 1).ToString(), Calibri);
                    table.AddCell(cellGray);
                    cellGray.Phrase = new Phrase(drivers[i].Sex == "М" ? "Мужчина" : "Женщина", Calibri);
                    table.AddCell(cellGray);
                    cellGray.Phrase = new Phrase(drivers[i].Age, Calibri);
                    table.AddCell(cellGray);
                    cellGray.Phrase = new Phrase(drivers[i].Experience, Calibri);
                    table.AddCell(cellGray);
                    cellGray.Phrase = new Phrase(drivers[i].Married, Calibri);
                    table.AddCell(cellGray);
                    cellGray.Phrase = new Phrase(drivers[i].Children, Calibri);
                    table.AddCell(cellGray);
                }
            }
            table.SpacingAfter = SpacingAfter;
            return table;
        }


        public PdfPTable DrawTable(List<Row> values, string header)
        {
            var table = new PdfPTable(4);
            table.WidthPercentage = 100f;
            table.DefaultCell.PaddingBottom = 4;
            table.DefaultCell.PaddingTop = 4;
            table.DefaultCell.BorderColor = ColorBorderDefault;

            var cellHeader = new PdfPCell(new Phrase(header, new Font(Base3Font, 12, 0, ColorBorderDefault)));
            cellHeader.BackgroundColor = ColorBackgroundDefault;
            cellHeader.HorizontalAlignment = Element.ALIGN_LEFT;
            cellHeader.Colspan = 4;
            cellHeader.PaddingBottom = 4;
            cellHeader.PaddingTop = 4;
            cellHeader.BorderColor = ColorBorderDefault;
            table.AddCell(cellHeader);

            var cellGray = new PdfPCell();
            cellGray.BackgroundColor = ColorBackgroundDefault;
            cellGray.HorizontalAlignment = Element.ALIGN_LEFT;
            cellGray.PaddingBottom = 4;
            cellGray.PaddingTop = 4;
            cellGray.BorderColor = ColorBorderDefault;

            var list = values.ToList();
            for (var i = 0; i < list.Count; i++)
            {
                if (i % 2 == 0)
                {
                    table.AddCell(new Phrase(list[i].Key1, CalibriBd));
                    table.AddCell(new Phrase(list[i].Value1, Calibri));
                    table.AddCell(new Phrase(list[i].Key2, CalibriBd));
                    table.AddCell(new Phrase(list[i].Value2, Calibri));
                }
                else
                {
                    cellGray.Phrase = new Phrase(list[i].Key1, CalibriBd);
                    table.AddCell(cellGray);
                    cellGray.Phrase = new Phrase(list[i].Value1, Calibri);
                    table.AddCell(cellGray);
                    cellGray.Phrase = new Phrase(list[i].Key2, CalibriBd);
                    table.AddCell(cellGray);
                    cellGray.Phrase = new Phrase(list[i].Value2, Calibri);
                    table.AddCell(cellGray);
                }
            }
            table.SpacingAfter = SpacingAfter;
            return table;
        }

        private static string GetDriver(int count)
        {
            switch (count)
            {
                case 1:
                    return count + " водитель";
                case 2:
                case 3:
                case 4: return count + " водителя";
                case 5: return count + " водителей";
                default:
                    return string.Empty;
            }
        }

        public class Footer : PdfPageEventHelper  
        {
            public override void OnEndPage(PdfWriter writer, Document document)
            {
                var model = IoC.Resolve<PdfModel>();
                model.AddFooter(document);
            }
        }
    }
}
